package com.starhub.monitor.service.impl;

import com.starhub.application.agent.dao.ChatSessionMapper;
import com.starhub.common.bean.agent.AgentConfig;
import com.starhub.engine.agent.dao.AgentConfigDao;
import com.starhub.engine.sys.user.dao.SysUserDao;
import com.starhub.monitor.dao.AIChatLogMapper;
import com.starhub.monitor.dto.ActivityLogDto;
import com.starhub.monitor.dto.AgentUsageStatsDto;
import com.starhub.monitor.dto.ChatLogDetailDto;
import com.starhub.monitor.dto.MonitorStatsDto;
import com.starhub.monitor.dto.SystemResourcesDto;
import com.starhub.monitor.service.IMonitorStatsService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.RuntimeMXBean;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.time.YearMonth;
import java.time.Year;

@Service
public class MonitorStatsServiceImpl implements IMonitorStatsService {

    @Autowired
    private AIChatLogMapper aiChatLogMapper;
    
    @Autowired
    private AgentConfigDao agentConfigDao;
    
    @Autowired
    private SysUserDao sysUserDao;
    
    @Autowired
    private ChatSessionMapper chatSessionMapper;
    
    @Override
    public Long getTodayTotalRequests() {
        LocalDateTime startOfDay = LocalDate.now().atStartOfDay();
        return aiChatLogMapper.countTodayRequests(startOfDay);
    }
    
    @Override
    public Long getTotalAgents() {
        AgentConfig query = new AgentConfig();
        query.setDeleteType(0); // 未删除的
        List<AgentConfig> agents = agentConfigDao.selectByPrimaryKeySelective(query);
        return (long) (agents != null ? agents.size() : 0);
    }

    @Override
    public Long getTotalUsers() {
        // 直接使用DAO层的统计方法获取活跃用户数
        return sysUserDao.countActiveUsers();
    }

    @Override
    public Long getTotalApiCalls() {
        // 获取API调用总次数
        return aiChatLogMapper.countTotalApiCalls();
    }

    @Override
    public Long getTotalConversations() {
        // 直接使用DAO层的统计方法获取活跃会话数
        return chatSessionMapper.countActiveSessions();
    }
    
    @Override
    public Long getTotalAlerts() {
        // 获取告警数量（状态为0的记录数量）
        return aiChatLogMapper.countTotalAlerts();
    }
    
    @Override
    public Long getTotalErrors() {
        // 获取错误数量（状态为0的记录数量）
        return aiChatLogMapper.countTotalErrors();
    }
    
    @Override
    public Long getTotalNormals() {
        // 获取正常数量（状态为1的记录数量）
        return aiChatLogMapper.countTotalNormals();
    }
    
    @Override
    public List<ActivityLogDto> getRecentActivityLogs(int limit) {
        List<Map<String, Object>> logs = aiChatLogMapper.getRecentActivityLogs(limit);
        List<ActivityLogDto> result = new ArrayList<>();
        
        for (Map<String, Object> log : logs) {
            result.add(ActivityLogDto.builder()
                    .userId((Long) log.get("user_id"))
                    .username((String) log.get("username"))
                    .name((String) log.get("name"))
                    .agentId((Long) log.get("agent_id"))
                    .status((Integer) log.get("status"))
                    .eventTime((LocalDateTime) log.get("request_time"))
                    .errorMessage((String) log.get("error_message"))
                    .requestContent((String) log.get("request_content"))
                    .build());
        }
        
        return result;
    }
    
    @Override
    public MonitorStatsDto getRequestStatsByTime(String type, String time) {
        LocalDateTime startTime;
        LocalDateTime endTime;
        List<TimeRange> timeRanges;
        
        // 根据类型和时间参数计算时间范围
        switch (type) {
            case "day":
                // 解析具体日期，如：2024-03-20
                startTime = LocalDateTime.parse(time + "T00:00:00");
                endTime = startTime.plusDays(1);
                timeRanges = createHourlyTimeRanges(startTime, endTime);
                break;
            case "week":
                // 解析年月周，如：2025-03-2 表示2025年3月第2周
                String[] weekParts = time.split("-");
                int year = Integer.parseInt(weekParts[0]);
                int month = Integer.parseInt(weekParts[1]);
                int weekNumber = Integer.parseInt(weekParts[2]);
                
                // 获取指定月份第1天
                LocalDate firstDayOfMonth = LocalDate.of(year, month, 1);
                // 获取该月第一天是周几
                int firstDayOfWeek = firstDayOfMonth.getDayOfWeek().getValue();
                // 计算第一周的起始日期（调整到周一）
                LocalDate weekStart = firstDayOfMonth.minusDays(firstDayOfWeek - 1);
                // 如果第一周起始日期在上个月，则从本月1号开始
                if (weekStart.getMonthValue() != month) {
                    weekStart = firstDayOfMonth;
                }
                // 计算目标周的起始日期
                weekStart = weekStart.plusWeeks(weekNumber - 1);
                // 如果目标周起始日期不在指定月份，则使用月份第一天
                if (weekStart.getMonthValue() != month) {
                    weekStart = firstDayOfMonth;
                }
                
                startTime = weekStart.atStartOfDay();
                endTime = weekStart.plusDays(7).atStartOfDay();
                // 如果结束时间超过了下个月，则调整到本月最后一天
                if (endTime.getMonthValue() != month) {
                    endTime = firstDayOfMonth.plusMonths(1).atStartOfDay();
                }
                
                timeRanges = createDailyTimeRanges(startTime, endTime);
                break;
            case "month":
                // 解析年份和月份，如：2025-1 表示2025年1月
                String[] monthParts = time.split("-");
                int monthYear = Integer.parseInt(monthParts[0]);
                int monthNum = Integer.parseInt(monthParts[1]);
                
                startTime = LocalDate.of(monthYear, monthNum, 1).atStartOfDay();
                endTime = startTime.plusMonths(1);
                timeRanges = createDailyTimeRanges(startTime, endTime);
                break;
            default:
                throw new IllegalArgumentException("Invalid type: " + type);
        }
        
        // 获取统计数据
        List<MonitorStatsDto.TimeStats> timeStats = getStatsByTimeRange(timeRanges);
        
        return MonitorStatsDto.builder()
                .timeStats(timeStats)
                .build();
    }
    
    @Override
    public MonitorStatsDto getDashboardStats() {
        return MonitorStatsDto.builder()
                .totalRequestsToday(getTodayTotalRequests())
                .totalAgents(getTotalAgents())
                .totalUsers(getTotalUsers())
                .totalApiCalls(getTotalApiCalls())
                .totalConversations(getTotalConversations())
                .totalAlerts(getTotalAlerts())
                .totalErrors(getTotalErrors())
                .totalNormals(getTotalNormals())
//                .timeStats(getRequestStatsByTime(type).getTimeStats())
                .build();
    }
    
    @Override
    public MonitorStatsDto getRequestStatsByCustomTimeRange(
            LocalDateTime startTime, LocalDateTime endTime, String interval) {
        List<TimeRange> timeRanges;
        
        switch (interval) {
            case "hour":
                timeRanges = createHourlyTimeRanges(startTime, endTime);
                break;
            case "day":
                timeRanges = createDailyTimeRanges(startTime, endTime);
                break;
            case "month":
                timeRanges = createMonthlyTimeRanges(startTime, endTime);
                break;
            default:
                timeRanges = createDailyTimeRanges(startTime, endTime);
        }
        
        return MonitorStatsDto.builder()
                .timeStats(getStatsByTimeRange(timeRanges))
                .build();
    }
    
    @Override
    public SystemResourcesDto getSystemResources() {
        // 获取CPU使用率 - 监控整个服务器的CPU使用率
        OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
        double cpuUsage = 0.0;
        
        try {
            // 先尝试使用OperatingSystemMXBean获取系统级CPU使用率
            if (osBean instanceof com.sun.management.OperatingSystemMXBean) {
                // 注意：getSystemCpuLoad已被弃用，在新版本中使用getCpuLoad
                // 但为了兼容性，我们先尝试使用getSystemCpuLoad，如果不可用再尝试其他方法
                try {
                    com.sun.management.OperatingSystemMXBean sunOsBean = (com.sun.management.OperatingSystemMXBean) osBean;
                    
                    // 由于JDK不同版本API变化，尝试通过反射调用getSystemCpuLoad()或getCpuLoad()
                    try {
                        java.lang.reflect.Method method = sunOsBean.getClass().getDeclaredMethod("getSystemCpuLoad");
                        method.setAccessible(true);
                        Double systemCpuLoad = (Double) method.invoke(sunOsBean);
                        if (systemCpuLoad != null && systemCpuLoad >= 0) {
                            cpuUsage = systemCpuLoad * 100;
                        }
                    } catch (NoSuchMethodException e) {
                        // 如果getSystemCpuLoad不存在，尝试getCpuLoad (JDK 14+)
                        try {
                            java.lang.reflect.Method method = sunOsBean.getClass().getDeclaredMethod("getCpuLoad");
                            method.setAccessible(true);
                            Double systemCpuLoad = (Double) method.invoke(sunOsBean);
                            if (systemCpuLoad != null && systemCpuLoad >= 0) {
                                cpuUsage = systemCpuLoad * 100;
                            }
                        } catch (Exception ex) {
                            // 忽略异常，稍后尝试其他方法
                        }
                    } catch (Exception e) {
                        // 忽略异常，稍后尝试其他方法
                    }
                } catch (Exception e) {
                    // 忽略异常，稍后尝试其他方法
                }
            }
            
            // 如果通过JMX获取失败，尝试通过运行系统命令获取
            if (cpuUsage <= 0) {
                String osName = System.getProperty("os.name").toLowerCase();
                if (osName.contains("linux")) {
                    // Linux系统 - 使用top命令获取CPU使用率
                    Process process = Runtime.getRuntime().exec("top -bn1");
                    process.waitFor();
                    java.io.BufferedReader reader = new java.io.BufferedReader(
                            new java.io.InputStreamReader(process.getInputStream()));
                    String line;
                    while ((line = reader.readLine()) != null) {
                        if (line.contains("Cpu(s)")) {
                            // 解析CPU使用率行
                            String[] parts = line.split(":|,");
                            for (String part : parts) {
                                if (part.contains("id")) {
                                    // 提取空闲CPU百分比
                                    double idleCpu = Double.parseDouble(part.replaceAll("[^0-9\\.]", "").trim());
                                    // 计算使用的CPU百分比
                                    cpuUsage = 100.0 - idleCpu;
                                    break;
                                }
                            }
                            break;
                        }
                    }
                    reader.close();
                } else if (osName.contains("windows")) {
                    // Windows系统 - 使用wmic命令获取CPU使用率
                    Process process = Runtime.getRuntime().exec("wmic cpu get loadpercentage");
                    process.waitFor();
                    java.io.BufferedReader reader = new java.io.BufferedReader(
                            new java.io.InputStreamReader(process.getInputStream()));
                    String line;
                    // 跳过标题行
                    reader.readLine();
                    while ((line = reader.readLine()) != null) {
                        line = line.trim();
                        if (!line.isEmpty()) {
                            try {
                                cpuUsage = Double.parseDouble(line);
                                break;
                            } catch (NumberFormatException e) {
                                // 忽略非数字行
                            }
                        }
                    }
                    reader.close();
                }
            }
        } catch (Exception e) {
            // 如果无法获取CPU信息，保持默认值0
        }
        
        // 获取服务器内存使用情况
        double memoryUsage = 0.0;
        try {
            if (osBean instanceof com.sun.management.OperatingSystemMXBean) {
                com.sun.management.OperatingSystemMXBean sunOsBean = (com.sun.management.OperatingSystemMXBean) osBean;
                // 获取整个系统的物理内存情况
                long totalPhysicalMemory = sunOsBean.getTotalPhysicalMemorySize();
                long freePhysicalMemory = sunOsBean.getFreePhysicalMemorySize();
                long usedPhysicalMemory = totalPhysicalMemory - freePhysicalMemory;
                
                memoryUsage = ((double) usedPhysicalMemory / totalPhysicalMemory) * 100.0;
            }
        } catch (Exception e) {
            // 如果无法获取内存信息，保持默认值0
        }
        
        // 获取服务器存储空间信息
        double usedStorage = 0.0;
        double totalStorage = 0.0;
        try {
            File root = new File("/");
            if (!root.exists()) {
                // 在Windows系统中使用C盘
                root = new File("C:\\");
            }
            
            // 如果仍然无法获取根目录，尝试获取当前目录
            if (!root.exists()) {
                root = new File(".");
            }
            
            if (root.exists()) {
                // 转换为GB单位
                totalStorage = root.getTotalSpace() / (1024.0 * 1024.0 * 1024.0);
                usedStorage = totalStorage - (root.getFreeSpace() / (1024.0 * 1024.0 * 1024.0));
            }
        } catch (Exception e) {
            // 如果无法获取存储信息，保持默认值0
        }
        
        // 获取系统启动时间
        long uptimeSeconds = 0;
        try {
            // 获取JVM运行时间，作为服务运行时间
            RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean();
            
            // 精确到秒
            uptimeSeconds = TimeUnit.MILLISECONDS.toSeconds(runtimeBean.getUptime());
        } catch (Exception e) {
            // 如果无法获取运行时间，保持默认值0
        }
        
        return SystemResourcesDto.builder()
                .cpuUsage(Math.round(cpuUsage * 100) / 100.0) // 保留两位小数
                .memoryUsage(Math.round(memoryUsage * 100) / 100.0) // 保留两位小数
                .usedStorage(Math.round(usedStorage * 100) / 100.0) // 保留两位小数
                .totalStorage(Math.round(totalStorage * 100) / 100.0) // 保留两位小数
                .uptimeSeconds(uptimeSeconds)
                .build();
    }
    
    /**
     * 定义时间范围数据结构
     */
    private static class TimeRange {
        private final LocalDateTime startTime;
        private final LocalDateTime endTime;
        private final String label;
        
        public TimeRange(LocalDateTime startTime, LocalDateTime endTime, String label) {
            this.startTime = startTime;
            this.endTime = endTime;
            this.label = label;
        }
        
        public LocalDateTime getStartTime() {
            return startTime;
        }
        
        public LocalDateTime getEndTime() {
            return endTime;
        }
        
        public String getLabel() {
            return label;
        }
    }
    
    /**
     * 创建按日统计的时间范围列表
     */
    private List<TimeRange> createDailyTimeRanges() {
        LocalDate today = LocalDate.now();
        LocalDateTime startOfDay = today.atStartOfDay();
        LocalDateTime endOfDay = today.atTime(LocalTime.MAX);
        return createHourlyTimeRanges(startOfDay, endOfDay);
    }
    
    /**
     * 创建按小时统计的自定义时间范围列表
     */
    private List<TimeRange> createHourlyTimeRanges(LocalDateTime startTime, LocalDateTime endTime) {
        List<TimeRange> ranges = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd HH:00");
        
        // 将开始时间调整到整点
        LocalDateTime currentHour = startTime.withMinute(0).withSecond(0).withNano(0);
        
        while (!currentHour.isAfter(endTime)) {
            LocalDateTime nextHour = currentHour.plusHours(1);
            LocalDateTime rangeEnd = nextHour.isAfter(endTime) ? endTime : nextHour;
            
            ranges.add(new TimeRange(
                    currentHour, 
                    rangeEnd.minusNanos(1), 
                    currentHour.format(formatter)));
            
            currentHour = nextHour;
        }
        
        return ranges;
    }
    
    /**
     * 创建按天统计的自定义时间范围列表
     */
    private List<TimeRange> createDailyTimeRanges(LocalDateTime startTime, LocalDateTime endTime) {
        List<TimeRange> ranges = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        
        // 将开始时间调整到当天开始
        LocalDate currentDate = startTime.toLocalDate();
        LocalDateTime currentDay = currentDate.atStartOfDay();
        
        while (!currentDay.isAfter(endTime)) {
            LocalDateTime nextDay = currentDay.plusDays(1);
            LocalDateTime rangeEnd = nextDay.isAfter(endTime) ? endTime : nextDay;
            
            ranges.add(new TimeRange(
                    currentDay, 
                    rangeEnd.minusNanos(1), 
                    currentDay.format(formatter)));
            
            currentDay = nextDay;
        }
        
        return ranges;
    }
    
    /**
     * 创建按月统计的自定义时间范围列表
     */
    private List<TimeRange> createMonthlyTimeRanges(LocalDateTime startTime, LocalDateTime endTime) {
        List<TimeRange> ranges = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM");
        
        // 将开始时间调整到当月开始
        LocalDate currentDate = startTime.toLocalDate().withDayOfMonth(1);
        LocalDateTime currentMonth = currentDate.atStartOfDay();
        
        while (!currentMonth.isAfter(endTime)) {
            LocalDateTime nextMonth = currentMonth.plusMonths(1);
            LocalDateTime rangeEnd = nextMonth.isAfter(endTime) ? endTime : nextMonth;
            
            ranges.add(new TimeRange(
                    currentMonth, 
                    rangeEnd.minusNanos(1), 
                    currentMonth.format(formatter)));
            
            currentMonth = nextMonth;
        }
        
        return ranges;
    }
    
    /**
     * 创建按周统计的时间范围列表
     */
    private List<TimeRange> createWeeklyTimeRanges() {
        List<TimeRange> ranges = new ArrayList<>();
        LocalDate today = LocalDate.now();
        LocalDate startOfWeek = today.minusDays(today.getDayOfWeek().getValue() - 1);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd");
        
        for (int i = 0; i < 7; i++) {
            LocalDate currentDate = startOfWeek.plusDays(i);
            LocalDateTime startTime = currentDate.atStartOfDay();
            LocalDateTime endTime = currentDate.atTime(LocalTime.MAX);
            String label = currentDate.format(formatter);
            
            ranges.add(new TimeRange(startTime, endTime, label));
        }
        
        return ranges;
    }
    
    /**
     * 创建按月统计的时间范围列表
     */
    private List<TimeRange> createMonthlyTimeRanges() {
        List<TimeRange> ranges = new ArrayList<>();
        LocalDate today = LocalDate.now();
        LocalDate startOfMonth = today.withDayOfMonth(1);
        int daysInMonth = today.lengthOfMonth();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd");
        
        for (int i = 0; i < daysInMonth; i++) {
            LocalDate currentDate = startOfMonth.plusDays(i);
            LocalDateTime startTime = currentDate.atStartOfDay();
            LocalDateTime endTime = currentDate.atTime(LocalTime.MAX);
            String label = currentDate.format(formatter);
            
            ranges.add(new TimeRange(startTime, endTime, label));
        }
        
        return ranges;
    }
    
    /**
     * 根据时间范围列表统计请求数据
     */
    private List<MonitorStatsDto.TimeStats> getStatsByTimeRange(List<TimeRange> timeRanges) {
        List<MonitorStatsDto.TimeStats> result = new ArrayList<>();
        
        for (TimeRange range : timeRanges) {
            // 直接从数据库查询成功和失败的数量
            Long successCount = aiChatLogMapper.countSuccessRequestsByTimeRange(
                    range.getStartTime(), range.getEndTime());
            Long failureCount = aiChatLogMapper.countFailureRequestsByTimeRange(
                    range.getStartTime(), range.getEndTime());
            Long alertCount = aiChatLogMapper.countAlertRequestsByTimeRange(
                    range.getStartTime(), range.getEndTime());
            
            result.add(MonitorStatsDto.TimeStats.builder()
                    .timeSlot(range.getLabel())
                    .successCount(successCount)
                    .failureCount(failureCount)
                    .alertCount(alertCount)
                    .build());
        }
        
        return result;
    }

    @Override
    public List<AgentUsageStatsDto> getAgentUsageStats() {
        // 获取智能体使用统计数据
        List<Map<String, Object>> stats = aiChatLogMapper.getAgentUsageStats();
        List<AgentUsageStatsDto> result = new ArrayList<>();
        
        for (Map<String, Object> stat : stats) {
            result.add(AgentUsageStatsDto.builder()
                    .agentId((Long) stat.get("agent_id"))
                    .agentName((String) stat.get("agent_name"))
                    .usageCount((Long) stat.get("usage_count"))
                    .build());
        }
        
        return result;
    }

    @Override
    public List<ChatLogDetailDto> getChatLogDetails(LocalDateTime startTime, LocalDateTime endTime, Integer status) {
        return aiChatLogMapper.getChatLogDetails(startTime, endTime, status);
    }
} 